package com.demo.security.utils.jackson;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.demo.security.utils.NumberUtils;

public class JacksonObject extends HashMap<String, Object> {

	private static final long serialVersionUID = 9123945244282661987L;

	public JacksonObject() {
		super();
	}

	public JacksonObject(int initialCapacity, float loadFactor) {
		super(initialCapacity, loadFactor);
	}

	public JacksonObject(int initialCapacity) {
		super(initialCapacity);
	}

	public JacksonObject(Map<String, Object> m) {
		super(m);
	}

	@SuppressWarnings("unchecked")
	public <T> T get(String key) {
		return (T) super.get(key);
	}

	public <T> T get(String... key) {
		if (key.length == 0) {
			return null;
		}
		JacksonObject obj = this;
		for (int i = 0; i < key.length - 1; i++) {
			obj = obj.getObj(key[i]);
		}
		return obj.get(key);
	}

	/**
	 * 依次获取keys的value，当遇到一个不为空的值时停止并返回
	 * 
	 * @param key
	 * @return
	 * @author OL
	 */
	public <T> T getIfNotNull(String... keys) {
		T value = null;
		for (String key : keys) {
			value = this.get(key);
			if (value != null) {
				break;
			}
		}
		return value;
	}

	public Short getShort(String key) {
		return NumberUtils.toShort(super.get(key));
	}

	public short getShortValue(String key) {
		return this.getShortValue(key, (short) 0);
	}

	public short getShortValue(String key, short defaultValue) {
		return NumberUtils.toShort(super.get(key), defaultValue);
	}

	public Integer getInteger(String key) {
		return NumberUtils.toInteger(super.get(key));
	}

	public int getIntValue(String key) {
		return this.getIntValue(key, 0);
	}

	public int getIntValue(String key, int defaultValue) {
		return NumberUtils.toInteger(super.get(key), defaultValue);
	}

	public Long getLong(String key) {
		return NumberUtils.toLong(super.get(key));
	}

	public long getLongValue(String key) {
		return this.getLongValue(key, 0);
	}

	public long getLongValue(String key, long defaultValue) {
		return NumberUtils.toLong(super.get(key), defaultValue);
	}

	public Double getDouble(String key) {
		return NumberUtils.toDouble(super.get(key));
	}

	public double getDoubleValue(String key) {
		return NumberUtils.toDouble(super.get(key), 0D);
	}

	public double getDoubleValue(String key, double defaultValue) {
		return NumberUtils.toDouble(super.get(key), defaultValue);
	}

	public Float getFloat(String key) {
		return NumberUtils.toFloat(super.get(key));
	}

	public float getFloatValue(String key) {
		return NumberUtils.toFloat(super.get(key), 0F);
	}

	public float getFloatValue(String key, float defaultValue) {
		return NumberUtils.toFloat(super.get(key), defaultValue);
	}

	public BigDecimal getBigDecimal(String key) {
		if (super.containsKey(key)) {
			Object obj = super.get(key);
			if (NumberUtils.isNumerical(obj)) {
				return new BigDecimal(obj.toString());
			}
		}
		return null;
	}

	public BigDecimal getBigDecimal(String key, int scale) {
		return this.getBigDecimal(key, scale, BigDecimal.ROUND_HALF_UP); // 四舍五入
	}

	public BigDecimal getBigDecimal(String key, int scale, int roundingMode) {
		BigDecimal bigDecimal = this.getBigDecimal(key);
		if (bigDecimal != null) {
			return bigDecimal.setScale(scale, roundingMode);
		}
		return bigDecimal;
	}

	public Boolean getBoolean(String key) {
		if (super.containsKey(key)) {
			Object obj = super.get(key);
			if (obj != null) {
				return Boolean.valueOf(obj.toString());
			}
		}
		return null;
	}

	public boolean getBooleanValue(String key) {
		return this.getBooleanValue(key, false);
	}

	public boolean getBooleanValue(String key, boolean defaultValue) {
		if (super.containsKey(key)) {
			Object obj = super.get(key);
			if (obj != null) {
				return Boolean.valueOf(obj.toString());
			}
		}
		return defaultValue;
	}

	public String getString(String key) {
		return this.getString(key, null);
	}

	public String getString(String key, String defaultValue) {
		if (super.containsKey(key)) {
			Object obj = super.get(key);
			if (obj != null) {
				return obj.toString();
			}
		}
		return defaultValue;
	}

	@SuppressWarnings("unchecked")
	public JacksonObject getObj(String key) {
		Object obj = this.get(key);
		if (obj == null) {
			return null;
		} else if (obj instanceof String) {
			throw new JacksonException("类型错误: String不能转换成JacksonObject.");
		} else if (obj instanceof Map) {
			return new JacksonObject((Map<String, Object>) obj);
		} else if (obj instanceof JacksonObject) {
			return (JacksonObject) obj;
		} else {
			return null;
		}
	}

	public JacksonObject getObj(String... key) {
		if (key.length == 0) {
			return null;
		}
		JacksonObject obj = this;
		for (int i = 0; i < key.length; i++) {
			obj = obj.getObj(key[i]);
		}
		return obj;
	}

	public JacksonArray getArray(String key) {
		Object object = super.get(key);
		if (object == null) {
			return null;
		} else if (object instanceof List) {
			List<JacksonObject> list = new ArrayList<JacksonObject>();
			((List<?>) object).forEach(o -> {
				list.add(JacksonUtils.toJsonObject(o));
			});
			return new JacksonArray(list);
		} else if (object instanceof String) {
			throw new JacksonException("类型错误: String不能转换成JacksonObject.");
		} else {
			return null;
		}
	}

	/**
	 * 将JSON格式的字符串解析成Json对象
	 * 
	 * @param text
	 * @return
	 * @author OL
	 */
	public static JacksonObject parse(String text) {
		JacksonObject obj = new JacksonObject();
		if (text == null || text.trim().length() == 0) {
			return obj;
		}
		obj = JacksonUtils.toJsonObject(text);
		return obj;
	}

	/**
	 * 判断指定键值是否相等
	 * 
	 * @param key
	 * @param value
	 * @return
	 * @author OL
	 */
	public boolean equalsValue(String key, Object value) {
		Object actualValue = this.get(key);
		if (value == null) {
			return actualValue == null;
		}
		return value == actualValue || value.equals(actualValue);
	}

	/**
	 * 判断指定键值是否为空<br>
	 * 为空返回true，否则返回false
	 * 
	 * @param key
	 * @return
	 * @author OL
	 */
	public boolean checkEmpty(String key) {
		Object value = this.get(key);
		return value == null || value.equals("");
	}

	/**
	 * 判断指定键值是否不为空<br>
	 * 不为空返回true，否则返回false
	 * 
	 * @param key
	 * @return
	 * @author OL
	 */
	public boolean checkNotEmpty(String key) {
		return !this.checkEmpty(key);
	}

	public boolean hasEmpty(String... keys) {
		for (int i = 0; i < keys.length; i++) {
			if (checkEmpty(keys[i])) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 检查多个键值之中是否有非空的值<br>
	 * 若有则返回true，否则返回false
	 * 
	 * @param keys
	 * @return
	 * @author OL
	 */
	public boolean hasNotEmpty(String... keys) {
		for (int i = 0; i < keys.length; i++) {
			if (checkNotEmpty(keys[i])) {
				return true;
			}
		}
		return false;
	}

	@Override
	public String toString() {
		return JacksonUtils.toJsonString(this);
	}

}
